package com.yeming.tinyid.service;

import com.yeming.tinyid.dal.entity.TinyIdToken;
import com.yeming.tinyid.dal.mapper.TinyIdTokenMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;

/**
 * @author yeming.gao
 * @Description: tinyid的token服务层（主要用于验证）
 * @date 2020/7/28 18:32
 */
@Service
public class TinyIdTokenService {

    private static final Logger LOGGER = LoggerFactory.getLogger(TinyIdTokenService.class);

    @Resource
    private TinyIdTokenMapper tinyIdTokenMapper;
    /**
     * key为token
     * value为bizType
     */
    private static Map<String, Set<String>> tokenbizTypes = new HashMap<>();

    /**
     * 1分钟刷新一次token
     */
    @Scheduled(cron = "0 0/1 * * * ?")
    public void refresh() {
        init();
        LOGGER.info("---->token已刷新");
    }

    /**
     * 实例化后立即查询数据库所有的token信息
     */
    @PostConstruct
    private synchronized void init() {
        LOGGER.info("token加载中......");
        List<TinyIdToken> list = queryAll();
        tokenbizTypes = converToMap(list);
        LOGGER.info("token加载完成, token size:{}", list == null ? 0 : list.size());
    }

    /**
     * 判断bizType下的token是否存在
     * @param bizType 业务类型
     * @param token token
     * @return boolean
     */
    public boolean canVisit(String bizType, String token) {
        if (StringUtils.isEmpty(bizType) || StringUtils.isEmpty(token)) {
            return false;
        }
        Set<String> bizTypes = tokenbizTypes.get(token);
        return (bizTypes != null && bizTypes.contains(bizType));
    }

    private Map<String, Set<String>> converToMap(List<TinyIdToken> list) {
        Map<String, Set<String>> map = new HashMap<>(64);
        if (list != null) {
            for (TinyIdToken tinyIdToken : list) {
                if (!map.containsKey(tinyIdToken.getToken())) {
                    map.put(tinyIdToken.getToken(), new HashSet<>());
                }
                map.get(tinyIdToken.getToken()).add(tinyIdToken.getBizType());
            }
        }
        return map;
    }

    private List<TinyIdToken> queryAll() {
        return tinyIdTokenMapper.selectAll();
    }
}
